//
//  UITextView+ExPlaceholder.m
//  OC-Example
//
//  Created by apang on 2018/8/28.
//  Copyright © 2018 apang.men All rights reserved.
//

#import "UITextView+ExPlaceholder.h"
#import <objc/runtime.h>

#define defaultPlaceholderColor [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:1]
#define defaultPlaceholderFont  [UIFont fontWithName:@".SFUIText" size:16]

@interface UITextView()
@property (nonatomic, strong) UILabel * ex_placeholderLabel;
@end

@implementation UITextView (ExPlaceholder)
#pragma mark - Swizzle Dealloc

- (void)instanceMethodExchange:(SEL)method originMethod:(SEL)originMethod {
    method_exchangeImplementations(class_getInstanceMethod(self.class, originMethod), class_getInstanceMethod(self.class, method));
}

- (void)swizzledDealloc {
    [self swizzledDealloc];
    NSLog(@"dealloc");
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [self removeObserver:self forKeyPath:@"text"];
}

static const char ExPlaceholderLabelKey = '\0';

- (void)setEx_placeholderLabel:(UILabel *)ex_placeholderLabel {
    if (ex_placeholderLabel != self.ex_placeholderLabel) {
        [self.ex_placeholderLabel removeFromSuperview];
        [self insertSubview:ex_placeholderLabel atIndex:0];
        [self willChangeValueForKey:@"ex_placeholderLabel"];
        objc_setAssociatedObject(self, &ExPlaceholderLabelKey, ex_placeholderLabel, OBJC_ASSOCIATION_ASSIGN);
        [self didChangeValueForKey:@"ex_placeholderLabel"];
    }
}

- (UILabel *)ex_placeholderLabel {
    return objc_getAssociatedObject(self, &ExPlaceholderLabelKey);
}

static const char OriginKey = '\0';

- (void)setOrigin:(CGPoint)origin {
    NSValue * value = [NSValue valueWithCGPoint:origin];
    objc_setAssociatedObject(self, &OriginKey, value, OBJC_ASSOCIATION_COPY_NONATOMIC);
    [self updatePlaceholder];
}

- (CGPoint)origin {
    NSValue * value = objc_getAssociatedObject(self, &OriginKey);
    CGPoint tmpPoint = value.CGPointValue;
    if(CGPointEqualToPoint(tmpPoint, CGPointZero)){
        tmpPoint = CGPointMake(self.textContainerInset.left+1, self.textContainerInset.top);
    }
    return tmpPoint;
}

static const char PlaceholderKey = '\0';

- (void)setPlaceholder:(NSString *)placeholder {
    objc_setAssociatedObject(self, &PlaceholderKey, placeholder, OBJC_ASSOCIATION_ASSIGN);
    [self updatePlaceholder];
}

- (NSString *)placeholder {
    return objc_getAssociatedObject(self, &PlaceholderKey);
}

static const char AttributedPlaceholderKey = '\0';

- (void)setAttributedPlaceholder:(NSAttributedString *)attributedPlaceholder {
    objc_setAssociatedObject(self, &AttributedPlaceholderKey, attributedPlaceholder, OBJC_ASSOCIATION_COPY_NONATOMIC);
    [self updatePlaceholder];
}

- (NSAttributedString *)attributedPlaceholder {
    return objc_getAssociatedObject(self, &AttributedPlaceholderKey);
}

static const char PlaceholderColorKey = '\0';

- (void)setPlaceholderColor:(UIColor *)placeholderColor {
    objc_setAssociatedObject(self, &PlaceholderColorKey, placeholderColor, OBJC_ASSOCIATION_ASSIGN);
    [self updatePlaceholder];
}

- (UIColor *)placeholderColor {
    UIColor * tmpColor = objc_getAssociatedObject(self, &PlaceholderColorKey);
    return (tmpColor == nil)?defaultPlaceholderColor:tmpColor;
}

static const char PlaceholderFontKey = '\0';

- (void)setPlaceholderFont:(UIFont *)placeholderFont {
    objc_setAssociatedObject(self, &PlaceholderFontKey, placeholderFont, OBJC_ASSOCIATION_ASSIGN);
    [self updatePlaceholder];
}

- (UIFont *)placeholderFont {
    UIFont * tmpFont = objc_getAssociatedObject(self, &PlaceholderFontKey);
    return (tmpFont == nil)?defaultPlaceholderFont:tmpFont;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"text"]) {
        [self textUpdate];
    }
}

- (void)updatePlaceholder {
    if(!self.ex_placeholderLabel){
        [self instanceMethodExchange:@selector(swizzledDealloc) originMethod:NSSelectorFromString(@"dealloc")];
        [self addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:nil];
        UILabel * label = [[UILabel alloc] init];
        self.ex_placeholderLabel = label;
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textUpdate) name:UITextViewTextDidChangeNotification object:self];
        if (self.text.length>0) {
            [self textUpdate];
        }
    }
    self.ex_placeholderLabel.textColor = self.placeholderColor;
    self.ex_placeholderLabel.font = self.placeholderFont;
    if(self.attributedPlaceholder){
        self.ex_placeholderLabel.attributedText = self.attributedPlaceholder;
    }else{
        self.ex_placeholderLabel.text = self.placeholder;
    }
    [self.ex_placeholderLabel sizeToFit];
    CGRect rect = self.ex_placeholderLabel.bounds;
    rect.origin = self.origin;
    self.ex_placeholderLabel.frame = rect;
}

- (void)textUpdate {
    if (self.text.length>0) {
        self.ex_placeholderLabel.hidden = YES;
    }else {
        self.ex_placeholderLabel.hidden = NO;
    }
}

- (void)prepareForInterfaceBuilder {
    [self updatePlaceholder];
}
@end
